package com.lzh.runke.core.web_base.autoconfigure;

import com.github.pagehelper.PageHelper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.boot.autoconfigure.AutoConfigurationExcludeFilter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.method.HandlerTypePredicate;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import javax.annotation.Resource;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import java.util.Properties;

//TODO

/**
 * @author LiuZiHao
 * @date 创建时间:2023年03月22日 14:45:58
 */
@Configuration
@Import(WebAutoConfiguration.AutoScannerRegistry.class)
@EnableConfigurationProperties(WebAutoConfigProperties.class)
@EnableScheduling
public class WebAutoConfiguration implements WebMvcConfigurer {

    @Resource
    private WebAutoConfigProperties webAutoConfigProperties;

//    @Bean
//    public PageHelper pageHelper() {
//        PageHelper pageHelper = new PageHelper();
//        Properties properties = new Properties();
//        properties.setProperty("helperDialect", "postgresql");
//        properties.setProperty("offsetAsPageNum", "false");
//        properties.setProperty("rowBoundsWithCount", "true");
//        properties.setProperty("pageSizeZero", "false");
//        properties.setProperty("reasonable", "false");
//        properties.setProperty("params", "pageNum=pageNo;pageSize=pageSize;count=countSql;reasonable=reasonable;pageSizeZero=pageSizeZero");
//        properties.setProperty("supportMethodsArguments", "true");
//        properties.setProperty("autoRuntimeDialect", "false");
//        properties.setProperty("closeConn", "true");
//        pageHelper.setProperties(properties);
//        return pageHelper;
//    }

//    @Bean
//    public Validator validator() {
//        HibernateValidatorConfiguration configure = Validation.byProvider(HibernateValidator.class)
//                .configure();
//
//        // 是否开启快速校验：遇到一个错误即中断
//        if (webAutoConfigProperties.isValidatorFailFast()) {
//            configure.addProperty("hibernate.validator.fail_fast", "true");
//        }
//        ValidatorFactory factory = configure.buildValidatorFactory();
//        return factory.getValidator();
//    }

    /**
     * 在Spring Boot中定制Jackson ObjectMapper
     * 使用ObjectMapper实例来序列化响应和反序列化请求。
     * 默认情况下，Spring Boot 配置将禁用以下功能：
     * <p>
     * MapperFeature.DEFAULT_VIEW_INCLUSION
     * DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES
     * SerializationFeature.WRITE_DATES_AS_TIMESTAMPS
     *
     * @return
     */
    @Bean
    @ConditionalOnMissingBean
    //修饰bean的一个注解，主要实现的是，当你的bean被注册之后，如果再注册相同类型的bean，就不会成功，它会保证你的bean只有一个，即你的实例只有一个。
    //如果不加@ConditionalOnMissingBean，当你注册多个相同的bean时，会出现异常，以此来告诉开发人员.
    public Jackson2ObjectMapperBuilder jackson2ObjectMapperBuilder() {
        return Jackson2ObjectMapperBuilder.json().timeZone("GMT+08");
    }

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        if (!webAutoConfigProperties.isCorsEnabled()) {
            return;
        }
        registry.addMapping("/**")
                .allowedOriginPatterns("*")
                .allowedMethods("GET", "POST", "OPTIONS")
                .allowedHeaders("*")
                .allowCredentials(true)
                .maxAge(3600);
    }


    /**
     * 公共路径配置
     * 仅@RestController生效
     *
     * @param configurer
     */
    @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {
        // 所有RestController路径映射都加上api前缀
        configurer.addPathPrefix(webAutoConfigProperties.getPathApi(), HandlerTypePredicate.forAnnotation(RestController.class));
    }


    @Slf4j
    static class AutoScannerRegistry implements BeanDefinitionRegistryPostProcessor {

        @Override
        public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
            ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(registry);
            scanner.addExcludeFilter(new AutoConfigurationExcludeFilter());
            int numOfBeans = scanner.scan("com.lzh.runke");
            log.info("Auto scanner registered {} beans", numOfBeans);
        }

        @Override
        public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {

        }
    }
}